home *** CD-ROM | disk | FTP | other *** search
/ Fritz: All Fritz / All Fritz.zip / All Fritz / FILES / PROGNG_C / MRUTC.LZH / TWINDOW.C < prev    next >
Text File  |  1988-04-10  |  14KB  |  658 lines

  1. /* ----------------------- twindow.c --------------------- */
  2.  
  3. #include <stdio.h>
  4. #include <ctype.h>
  5. #include <stdarg.h>
  6. #include <dos.h>
  7. #include <alloc.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include "twindow.h"
  11. #include "keys.h"
  12.  
  13. #define TABS 4
  14. #define SCRNHT 25
  15. #define SCRNWIDTH 80
  16. #define ON  1
  17. #define OFF 0
  18. #define ERROR -1
  19.  
  20. /* -------- local prototypes ---------- */
  21. static void redraw(WINDOW *wnd);
  22. static void wframe(WINDOW *wnd);
  23. static void dtitle(WINDOW *wnd);
  24. static int *waddr(WINDOW *wnd, int x, int y);
  25. static void vswap(WINDOW *wnd);
  26. static void vsave(WINDOW *wnd);
  27. static void vrstr(WINDOW *wnd);
  28. static void add_list(WINDOW *wnd);
  29. static void beg_list(WINDOW *wnd);
  30. static void remove_list(WINDOW *wnd);
  31. static void insert_list(WINDOW *w1, WINDOW *w2);
  32. #ifndef FASTWINDOWS
  33. static int verify_wnd(WINDOW **w1);
  34. static int dget(WINDOW *wnd, int x, int y);
  35. #endif
  36. /*page*/
  37. /* ---- array of border character sets ------ */
  38. struct {
  39.     int nw, ne, se, sw, side, line;
  40. } wcs[] = {
  41.     {218,191,217,192,179,196},    /* single line */
  42.     {201,187,188,200,186,205},    /* double line */
  43.     {214,183,189,211,186,196},    /* single top, double side */
  44.     {213,184,190,212,179,205},    /* double top, single side */
  45.     {194,194,217,192,179,196}    /* pop-down menu */
  46. };
  47.  
  48. /* ---- window structure linked list head & tail ---- */
  49. WINDOW *listhead = NULL;
  50. WINDOW *listtail = NULL;
  51. int VSG;    /* video segment address */
  52.  
  53. /* ----------- establish a new window -------------- */
  54. WINDOW *establish_window(x, y, h, w)
  55. {
  56.     WINDOW *wnd;
  57.  
  58.     VSG = (vmode() == 7 ? 0xb000 : 0xb800);
  59.     if ((wnd = (WINDOW *) malloc(sizeof (WINDOW))) == NULL)
  60.         return NULL;
  61.     /* ------- adjust for out-of bounds parameters ------- */
  62.     WTITLE = "";
  63.     HEIGHT = min(h, SCRNHT);
  64.     WIDTH = min(w, SCRNWIDTH);
  65.     COL = max(0, min(x, SCRNWIDTH-WIDTH));
  66.     ROW = max(0, min(y, SCRNHT-HEIGHT));
  67.     WCURS = 0;
  68.     SCROLL = 0;
  69.     SELECT = 1;
  70.     BTYPE = 0;
  71.     VISIBLE = HIDDEN = 0;
  72.     PREV = NEXT = NULL;
  73.     FHEAD = FTAIL = NULL;
  74.     WBORDER=WNORMAL=PNORMAL=WTITLEC =
  75.                 clr(BLACK, WHITE, BRIGHT);
  76.     WACCENT = clr(WHITE, BLACK, DIM);
  77.     if ((SAV = malloc(WIDTH * HEIGHT * 2)) == (char *) 0)
  78.         return NULL;
  79.     add_list(wnd);
  80. #ifndef FASTWINDOWS
  81.     clear_window(wnd);
  82.     wframe(wnd);
  83. #endif
  84.     return wnd;
  85. }
  86.  
  87. /* ------ set the window's border --------- */
  88. void set_border(WINDOW *wnd, int btype)
  89. {
  90.     if (verify_wnd(&wnd))    {
  91.         BTYPE = btype;
  92.         redraw(wnd);
  93.     }
  94. }
  95.  
  96. /* ------- set colors ----------- */
  97. void set_colors(WINDOW *wnd,int area,int bg,int fg,int inten)
  98. {
  99.     if (vmode() == 7)    {
  100.         if (bg != WHITE && bg != BLACK)
  101.             return;
  102.         if (fg != WHITE && fg != BLACK)
  103.             return;
  104.     }
  105.     if (verify_wnd(&wnd))    {
  106.         if (area == ALL)
  107.             while (area)
  108.                 WCOLOR [--area] = clr(bg, fg, inten);
  109.         else
  110.             WCOLOR [area] = clr(bg, fg, inten);
  111.         redraw(wnd);
  112.     }
  113. }
  114. /*page*/
  115. /* ----- set the intensity of a window ------ */
  116. void set_intensity(WINDOW *wnd, int inten)
  117. {
  118.     int area = ALL;
  119.  
  120.     if (verify_wnd(&wnd))    {
  121.         while (area)    {
  122.             WCOLOR [--area] &= ~BRIGHT;
  123.             WCOLOR [area] |= inten;
  124.         }
  125.         redraw(wnd);
  126.     }
  127. }
  128.  
  129. /* -------- set title ------------- */
  130. void set_title(WINDOW *wnd, char *title)
  131. {
  132.     if (verify_wnd(&wnd))    {
  133.         WTITLE = title;
  134.         redraw(wnd);
  135.     }
  136. }
  137.  
  138. /* ------ redraw a window when an attribute changes ----- */
  139. static void redraw(WINDOW *wnd)
  140. {
  141. #ifndef FASTWINDOWS
  142.     int x, y, chat, atr;
  143.  
  144.     for (y = 1; y < HEIGHT-1; y++)
  145.         for (x = 1; x < WIDTH-1; x++)    {
  146.             chat = dget(wnd, x, y);
  147.             atr = (((chat>>8)&255) ==
  148.                 PNORMAL ? WNORMAL : WACCENT);
  149.             displ(wnd, x, y, chat&255, atr);
  150.         }
  151.     wframe(wnd);
  152. #endif
  153.     PNORMAL = WNORMAL;
  154. }
  155.  
  156. /* ------------ display an established window ------------ */
  157. void display_window(WINDOW *wnd)
  158. {
  159.     if (verify_wnd(&wnd) && !VISIBLE)    {
  160.         VISIBLE = 1;
  161. #ifdef FASTWINDOWS
  162.         if (HIDDEN)    {
  163.             HIDDEN = 0;
  164.             vrstr(wnd);
  165.         }
  166.         else    {
  167.             vsave(wnd);
  168.             clear_window(wnd);
  169.             wframe(wnd);
  170.         }
  171. #else
  172.         vswap(wnd);
  173. #endif
  174.     }
  175. }
  176.  
  177. /* ---------- close all windows -------------- */
  178. void close_all()
  179. {
  180.     WINDOW *sav, *wnd = listtail;
  181.  
  182.     while (wnd)    {
  183.         sav = PREV;
  184.         delete_window(wnd);
  185.         wnd = sav;
  186.     }
  187. }
  188. /*page*/
  189. /* ------------ remove a window ------------------ */
  190. void delete_window(WINDOW *wnd)
  191. {
  192.     if (verify_wnd(&wnd))        {
  193.         remove_delist(wnd);
  194.         hide_window(wnd);
  195.         free(SAV);
  196.         remove_list(wnd);    /* remove window from list */
  197.         free(wnd);
  198.     }
  199. }
  200.  
  201. /* ------ remove the data entry list from a window ------ */
  202. void remove_delist(WINDOW *wnd)
  203. {
  204.     FIELD *fld, *fl;
  205.  
  206.     fld = FHEAD;
  207.     while (fld)    {
  208.         fl = fld->fnxt;
  209.         free(fld);
  210.         fld = fl;
  211.     }
  212. }
  213.  
  214. /* ----------- hide a window --------------- */
  215. void hide_window(WINDOW *wnd)
  216. {
  217.     if (verify_wnd(&wnd) && VISIBLE)    {
  218. #ifndef FASTWINDOWS
  219.         vswap(wnd);
  220. #else
  221.         vrstr(wnd);
  222. #endif
  223.         HIDDEN = 1;
  224.         VISIBLE = 0;
  225.     }
  226. }
  227. /*page*/
  228. #ifndef FASTWINDOWS
  229. /* ------ reposition the window in its 3-axis plane ------ */
  230. void repos_wnd(WINDOW *wnd, int x, int y, int z)
  231. {
  232.     WINDOW *twnd;
  233.     int x1, y1, chat;
  234.     if (!verify_wnd(&wnd))
  235.         return;
  236.     twnd = establish_window(x+COL, y+ROW, HEIGHT, WIDTH);
  237.     twnd->_tl = WTITLE;
  238.     twnd->btype = BTYPE;
  239.     twnd->wcolor[BORDER] = WBORDER;
  240.     twnd->wcolor[TITLE] = WTITLEC;
  241.     twnd->wcolor[ACCENT] = WACCENT;
  242.     twnd->wcolor[NORMAL] = WNORMAL;
  243.     twnd->_pn = PNORMAL;
  244.     twnd->_wsp = SCROLL;
  245.     twnd->_cr = WCURS;
  246.     twnd->_fh = FHEAD;
  247.     twnd->_ft = FTAIL;
  248.     if (z != 1)    {
  249.         remove_list(twnd);
  250.         if (z == 0)
  251.             insert_list(twnd, wnd);
  252.         else
  253.             beg_list(twnd);
  254.     }
  255.     for (y1 = 0; y1 < twnd->_wh; y1++)
  256.         for (x1 = 0; x1 < twnd->_ww; x1++)    {
  257.             chat = dget(wnd, x1, y1);
  258.             displ(twnd, x1, y1, chat&255, (chat>>8)&255);
  259.         }
  260.     twnd->_wv = 1;
  261.     vswap(twnd);
  262.     hide_window(wnd);
  263.     free(SAV);
  264.     remove_list(wnd);
  265.     *wnd = *twnd;
  266.     insert_list(wnd, twnd);
  267.     remove_list(twnd);
  268.     free(twnd);
  269. }
  270. #endif
  271.  
  272. /* ----------- clear the window area -------------- */
  273. void clear_window(WINDOW *wnd)
  274. {
  275.     register int x1, y1;
  276.  
  277.     if (verify_wnd(&wnd))
  278.         for (y1 = 1; y1 < HEIGHT-1; y1++)
  279.             for (x1 = 1; x1 < WIDTH-1; x1++)
  280.                 displ(wnd,x1, y1, ' ', WNORMAL);
  281. }
  282.  
  283. /* ------------ draw the window frame --------------- */
  284. static void wframe(WINDOW *wnd)
  285. {
  286.     register int x1, y1;
  287.  
  288.     if (!verify_wnd(&wnd))
  289.         return;
  290.     /* --------- window title -------------- */
  291.     displ(wnd,0, 0, NW, WBORDER);
  292.     dtitle(wnd);
  293.     displ(wnd,WIDTH-1, 0, NE, WBORDER);
  294.     /* ------------ window sides ----------------- */
  295.     for (y1 = 1; y1 < HEIGHT-1; y1++)    {
  296.         displ(wnd,0, y1, SIDE, WBORDER);
  297.         displ(wnd,WIDTH-1, y1, SIDE, WBORDER);
  298.     }
  299.     /* --------------- bottom of frame ---------------- */
  300.     displ(wnd,0, y1, SW, WBORDER);
  301.     for (x1 = 1; x1 < WIDTH-1; x1++)
  302.         displ(wnd,x1, y1, LINE, WBORDER);
  303.     displ(wnd,x1, y1, SE, WBORDER);
  304. }
  305. /*page*/
  306. /* ------------- displ the window title -------------------- */
  307. static void dtitle(WINDOW *wnd)
  308. {
  309.     int x1 = 1, i, ln;
  310.     char *s = WTITLE;
  311.  
  312.     if (!verify_wnd(&wnd))
  313.         return;
  314.     if (s)    {
  315.         ln = strlen(s);
  316.         if (ln > WIDTH-2)
  317.             i = 0;
  318.         else
  319.             i = ((WIDTH-2-ln) / 2);
  320.         if (i > 0)
  321.             while (i--)
  322.                 displ(wnd, x1++, 0, LINE, WBORDER);
  323.         while (*s && x1 < WIDTH-1)
  324.             displ(wnd, x1++, 0, *s++, WTITLEC);
  325.     }
  326.     while (x1 < WIDTH-1)
  327.         displ(wnd, x1++, 0, LINE, WBORDER);
  328. }
  329.  
  330. /* ------------- window-oriented printf ---------------- */
  331. void wprintf(WINDOW *wnd, char *ln, ...)
  332. {
  333.     char dlin [100], *dl = dlin;
  334.  
  335.     if (verify_wnd(&wnd))        {
  336.         va_list ap;
  337.         va_start(ap, ln);
  338.         vsprintf(dlin, ln, ap);
  339.         va_end(ap);
  340.         while (*dl)
  341.             wputchar(wnd, *dl++);
  342.     }
  343. }
  344. /*page*/
  345. /* ------------ write a character to the window ---------- */
  346. void wputchar(WINDOW *wnd, int c)
  347. {
  348.     if (!verify_wnd(&wnd))
  349.         return;
  350.     switch (c)    {
  351.         case '\n':
  352.             if (SCROLL == HEIGHT-3)
  353.                 scroll(wnd, UP);
  354.             else
  355.                 SCROLL++;
  356.             WCURS = 0;
  357.             break;
  358.         case '\t':
  359.             do displ(wnd,(WCURS++)+3,SCROLL+1,' ',WNORMAL);
  360.                 while ((WCURS%TABS) && (WCURS+1) < WIDTH-1);
  361.             break;
  362.         default:
  363.             if ((WCURS+1) < WIDTH-1)    {
  364.                 displ(wnd, WCURS+1, SCROLL+1, c, WNORMAL);
  365.                 WCURS++;
  366.             }
  367.             break;
  368.     }
  369. }
  370.  
  371. /* ------- set window cursor --------- */
  372. void wcursor(WINDOW *wnd, int x, int y)
  373. {
  374.     if (verify_wnd(&wnd) && x < WIDTH-1 && y < HEIGHT-1)    {
  375.         WCURS = x;
  376.         SCROLL = y;
  377.         cursor(COL+x+1, ROW+y+1);
  378.     }
  379. }
  380. /*page*/
  381. /* ------ allow the user to make a window selection ------ */
  382. int get_selection(WINDOW *wnd, int s, char *keys)
  383. {
  384.     int c = 0, ky;
  385.     if (!verify_wnd(&wnd))
  386.         return 0;
  387.     SELECT = s;
  388.     while (c != ESC && c != '\r' && c != BS && c != FWD)    {
  389.         accent(wnd);
  390.         c = get_char();
  391.         deaccent(wnd);
  392.         switch (c)        {
  393.             case UP:    if (SELECT >  1)
  394.                             SELECT--;
  395.                         else
  396.                             SELECT = SCROLL+1;
  397.                         break;
  398.             case DN:    if (SELECT < SCROLL+1)
  399.                             SELECT++;
  400.                         else 
  401.                             SELECT = 1;
  402.                         break;
  403.             case '\r':
  404.             case ESC:
  405.             case FWD:
  406.             case BS:    break;
  407.             default:    if (keys)    {
  408.                             ky = 0;
  409.                             while (*(keys + ky))    {
  410.                                 if (*(keys+ky)==toupper(c) ||
  411.                                     *(keys+ky)==tolower(c))
  412.                                     return ky + 1;
  413.                                 ky++;
  414.                             }
  415.                         }
  416.                         break;
  417.         }
  418.     }
  419.     return     c == '\r' ? SELECT : c == ESC ? 0 : c;
  420. }
  421.  
  422. union REGS rg;
  423.  
  424. /* ------- scroll a window's contents up or down --------- */
  425. void scroll(WINDOW *wnd, int dir)
  426. {
  427.     int row = HEIGHT-1, col, chat;
  428.  
  429.     if (!verify_wnd(&wnd))
  430.         return;
  431.     if (NEXT == NULL && HEIGHT > 3 && VISIBLE)    {
  432.         rg.h.ah = dir == UP ? 6 : 7;
  433.         rg.h.al = 1;
  434.         rg.h.bh = WNORMAL;
  435.         rg.h.cl = COL + 1;
  436.         rg.h.ch = ROW + 1;
  437.         rg.h.dl = COL + WIDTH - 2;
  438.         rg.h.dh = ROW + HEIGHT - 2;
  439.         int86(16, &rg, &rg);
  440.         return;
  441.     }
  442.     if (dir == UP)    {
  443.         for (row = 2; row < HEIGHT-1; row++)
  444.             for (col = 1; col < WIDTH-1; col++)    {
  445.                 chat = dget(wnd, col, row);
  446.                 displ(wnd,col,row-1,chat&255,(chat>>8)&255);
  447.             }
  448.         for (col = 1; col < WIDTH-1; col++)
  449.             displ(wnd, col, row-1, ' ', WNORMAL);
  450.     }
  451.     else    {
  452.         for (row = HEIGHT-2; row > 1; --row)
  453.             for (col = 1; col < WIDTH-1; col++)    {
  454.                 chat = dget(wnd, col, row-1);
  455.                 displ(wnd,col,row,chat&255,(chat>>8)&255);
  456.             }
  457.         for (col = 1; col < WIDTH-1; col++)
  458.             displ(wnd, col, row, ' ', WNORMAL);
  459.     }
  460. }
  461. /*page*/
  462. #ifndef FASTWINDOWS
  463. /* --- compute address of a window's display character --- */
  464. static int *waddr(WINDOW *wnd, int x, int y)
  465. {
  466.     WINDOW *nxt = NEXT;
  467.     int *vp;
  468.  
  469.     if (!VISIBLE)
  470.         return (int *) (SAV+y*(WIDTH*2)+x*2);
  471.     x += COL;
  472.     y += ROW;
  473.     while (nxt)    {
  474.         if (nxt->_wv)
  475.             if (x >= nxt->_wx && x <= nxt->_wx + nxt->_ww-1)
  476.                 if (y >= nxt->_wy &&
  477.                         y <= nxt->_wy + nxt->_wh-1)    {
  478.                     x -= nxt->_wx;
  479.                     y -= nxt->_wy;
  480.                     vp = (int *)
  481.                         ((nxt->_ws) +y*(nxt->_ww*2)+x*2);
  482.                     return vp;
  483.                 }
  484.         nxt = nxt->_nx;
  485.     }
  486.     return NULL;
  487. }
  488.  
  489. /* ---------- display a character to a window --------- */
  490. void displ(WINDOW *wnd, int x, int y, int ch, int at)
  491. {
  492.     int *vp;
  493.     int vch = (ch&255)|(at<<8);
  494.  
  495.     if ((vp = waddr(wnd, x, y)) != NULL)
  496.         *vp = vch;
  497.     else
  498.         vpoke(VSG,vad(x+COL,y+ROW),vch);
  499. }
  500. /*page*/
  501. /* ----- get a displayed character from a window ----- */
  502. static int dget(WINDOW *wnd, int x, int y)
  503. {
  504.     int *vp;
  505.  
  506.     if ((vp = waddr(wnd, x, y)) != NULL)
  507.         return *vp;
  508.     return vpeek(VSG,vad(x+COL,y+ROW));
  509. }
  510.  
  511. /* ------------- low-level video functions --------------- */
  512.  
  513. /* ------- swap the video image with the save buffer ----- */
  514. static void vswap(WINDOW *wnd)
  515. {
  516.     int x, y, chat;
  517.     int *bf = (int *) SAV;
  518.  
  519.     for (y = 0; y < HEIGHT; y++)
  520.         for (x = 0; x < WIDTH; x++)    {
  521.             chat = *bf;
  522.             *bf++ = dget(wnd, x, y);
  523.             displ(wnd, x, y, chat&255, (chat>>8)&255);
  524.         }
  525. }
  526.  
  527. #else
  528.  
  529. /* -------- save video memory into the save buffer ---- */
  530. static void vsave(WINDOW *wnd)
  531. {
  532.     int x, y;
  533.     int *bf = (int *) SAV;
  534.  
  535.     for (y = 0; y < HEIGHT; y++)
  536.         for (x = 0; x < WIDTH; x++)
  537.             *bf++ = vpeek(VSG, vad(x+COL, y+ROW));
  538. }
  539. /*page*/
  540. /* ----- restore video memory from the save buffer ----- */
  541. static void vrstr(WINDOW *wnd)
  542. {
  543.     int x, y;
  544.     int *bf = (int *) SAV;
  545.  
  546.     for (y = 0; y < HEIGHT; y++)
  547.         for (x = 0; x < WIDTH; x++)
  548.             vpoke(VSG,vad(x+COL,y+ROW), *bf++);
  549. }
  550. #endif
  551.  
  552. /* ----- (de)accent the line where SELECT points ------- */
  553. void acline(WINDOW *wnd, int set)
  554. {
  555.     int x, ch;
  556.  
  557.     if (!verify_wnd(&wnd))
  558.         return;
  559.     for (x = 1; x < WIDTH - 1; x++)    {
  560.         ch = dget(wnd, x, SELECT) & 255;
  561.         displ(wnd, x, SELECT, ch, set);
  562.     }
  563. }
  564.  
  565. /* ---------- linked list functions --------- */
  566.  
  567. /* ----- add a window to the end of the list ------ */
  568. static void add_list(WINDOW *wnd)
  569. {
  570.     if (listtail)    {
  571.         PREV = listtail;
  572.         listtail->_nx = wnd;
  573.     }
  574.     listtail = wnd;
  575.     if (!listhead)
  576.         listhead = wnd;
  577. }
  578. /*page*/
  579. /* ----- add a window to the beginning of the list ------ */
  580. static void beg_list(WINDOW *wnd)
  581. {
  582.     if (listhead)    {
  583.         NEXT = listhead;
  584.         listhead->_pv = wnd;
  585.     }
  586.     listhead = wnd;
  587.     if (!listtail)
  588.         listtail = wnd;
  589. }
  590.  
  591. /* --------- remove a window from the list -------- */
  592. static void remove_list(WINDOW *wnd)
  593. {
  594.     if (NEXT)
  595.         NEXT->_pv = PREV;
  596.     if (PREV)
  597.         PREV->_nx = NEXT;
  598.     if (listhead == wnd)
  599.         listhead = NEXT;
  600.     if (listtail == wnd)
  601.         listtail = PREV;
  602.     NEXT = PREV = NULL;
  603. }
  604.  
  605. /* ----- insert w1 after w2 ------ */
  606. static void insert_list(WINDOW *w1, WINDOW *w2)
  607. {
  608.     w1->_pv = w2;
  609.     w1->_nx = w2->_nx;
  610.     w2->_nx = w1;
  611.     if (w1->_nx == NULL)
  612.         listtail = w1;
  613.     else
  614.         w1->_nx->_pv = w1;
  615. }
  616. /*page*/
  617. #ifndef FASTWINDOWS
  618. /* ---- verify the presence of a window in the list ----- */
  619. static int verify_wnd(WINDOW **w1)
  620. {
  621.     WINDOW *wnd;
  622.  
  623.     wnd = listhead;
  624.     if (*w1 == NULL)
  625.         *w1 = listtail;
  626.     else    {
  627.         while (wnd != NULL)    {
  628.             if (*w1 == wnd)
  629.                 break;
  630.             wnd = NEXT;
  631.         }
  632.     }
  633.     return wnd != NULL;
  634. }
  635. #endif
  636.  
  637. WINDOW *ewnd = NULL;
  638.  
  639. /* ------- error messages ------- */
  640. void error_message(char *s)
  641. {
  642.     ewnd = establish_window(50, 22, 3, max(10, strlen(s)+2));
  643.     set_colors(ewnd, ALL, RED, YELLOW, BRIGHT);
  644.     set_title(ewnd, " ERROR! ");
  645.     display_window(ewnd);
  646.     wprintf(ewnd, s);
  647.     putchar(BELL);
  648. }
  649.  
  650. void clear_message()
  651. {
  652.     if (ewnd)
  653.         delete_window(ewnd);
  654.     ewnd = NULL;
  655. }
  656.  
  657.  
  658.